#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include "ls.h"

void print_file_info(struct stat *fileStat, const char *name, int show_inode, int long_format) {
    if (show_inode) {
        printf("%ld ", fileStat->st_ino);
    }
    if (long_format) {
        printf((S_ISDIR(fileStat->st_mode)) ? "d" : "-");
        printf((fileStat->st_mode & S_IRUSR) ? "r" : "-");
        printf((fileStat->st_mode & S_IWUSR) ? "w" : "-");
        printf((fileStat->st_mode & S_IXUSR) ? "x" : "-");
        printf((fileStat->st_mode & S_IRGRP) ? "r" : "-");
        printf((fileStat->st_mode & S_IWGRP) ? "w" : "-");
        printf((fileStat->st_mode & S_IXGRP) ? "x" : "-");
        printf((fileStat->st_mode & S_IROTH) ? "r" : "-");
        printf((fileStat->st_mode & S_IWOTH) ? "w" : "-");
        printf((fileStat->st_mode & S_IXOTH) ? "x" : "-");
        printf(" %ld", fileStat->st_nlink);
        printf(" %s", getpwuid(fileStat->st_uid)->pw_name);
        printf(" %s", getgrgid(fileStat->st_gid)->gr_name);
        printf(" %5ld", fileStat->st_size);
        char timebuf[80];
        strftime(timebuf, sizeof(timebuf), "%b %d %H:%M", localtime(&(fileStat->st_mtime)));
        printf(" %s", timebuf);
    }
    printf(" %s\n", name);
}

void list_directory(const char *path, int show_all, int long_format, int show_inode, int recursive) {
    DIR *dir;
    struct dirent *entry;
    struct stat fileStat;
    char full_path[1024];

    if ((dir = opendir(path)) == NULL) {
        perror("opendir");
        return;
    }

    while ((entry = readdir(dir)) != NULL) {
        if (!show_all && entry->d_name[0] == '.') {
            continue;
        }

        snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name);
        if (stat(full_path, &fileStat) < 0) {
            perror("stat");
            continue;
        }

        print_file_info(&fileStat, entry->d_name, show_inode, long_format);

        if (recursive && S_ISDIR(fileStat.st_mode) && 
            strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
            printf("\n%s:\n", full_path);
            list_directory(full_path, show_all, long_format, show_inode, recursive);
        }
    }

    closedir(dir);
}

int ls_main(int argc, char *argv[]) {
    int show_all = 0, long_format = 0, show_inode = 0, recursive = 0, dir_only = 0;
    const char *path = ".";

    for (int i = 1; i < argc; ++i) {
        if (argv[i][0] == '-') {
            for (int j = 1; argv[i][j] != '\0'; ++j) {
                switch (argv[i][j]) {
                    case 'a': show_all = 1; break;
                    case 'l': long_format = 1; break;
                    case 'i': show_inode = 1; break;
                    case 'R': recursive = 1; break;
                    case 'd': dir_only = 1; break;
                    default:
                        fprintf(stderr, "Unknown option: -%c\n", argv[i][j]);
                        return 1;
                }
            }
        } else {
            path = argv[i];
        }
    }

    if (dir_only) {
        struct stat fileStat;
        if (stat(path, &fileStat) < 0) {
            perror("stat");
            return 1;
        }
        print_file_info(&fileStat, path, show_inode, long_format);
    } else {
        list_directory(path, show_all, long_format, show_inode, recursive);
    }

    return 0;
}
